#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <cerrno>

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>

#include "gingko.h"

static pthread_mutex_t g_bw_up_mutex PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t g_bw_down_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t g_disk_r_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t g_disk_w_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t g_mk_seed_mutex = PTHREAD_MUTEX_INITIALIZER;

void bw_down_limit(int amount, int limit_rate)
{
    static struct timeval bw_down_start;
    static struct timeval bw_down_end;

    static int down_lamt;
    static int down_thresh = 16384;

    GKO_UINT64 waitlen;
    struct timespec ts;
    struct timespec rm;

    if (amount <= 0 || limit_rate <= 0) return;

    pthread_mutex_lock(&g_bw_down_mutex); // lock pthread mutex

    if ( UNLIKELY(!timerisset(&bw_down_start)) )
    {
        gettimeofday(&bw_down_start, NULL);
        goto DISK_W_UNLOCK_RET;
    }

    down_lamt += amount;
    if (down_lamt < down_thresh)
    {
        goto DISK_W_UNLOCK_RET;
    }

    gettimeofday(&bw_down_end, NULL);
    timersub(&bw_down_end, &bw_down_start, &bw_down_end);
    if (!timerisset(&bw_down_end))
    {
        goto DISK_W_UNLOCK_RET;
    }

    // TODO:


DISK_W_UNLOCK_RET:
    pthread_mutex_unlock(&g_bw_down_mutex); // unlock pthread mutex
}

void bw_up_limit(int amount, int limit_rate)
{
    static struct timeval bw_up_start;
    static struct timeval bw_up_end;
    static int up_lamt;
    static int up_thresh = 16384;
    GKO_UINT64 waitlen;
    struct timespec ts;
    struct timespec rm;


}

void disk_w_limit(int amount, int limit_rate)
{

}

void disk_r_limit(int amount, int limit_rate)
{

}

void mk_seed_limit(int amount, int limit_rate)
{
    
}